import time
import pygame
import threading
import random
from tkinter import messagebox
from pygame.locals import *
'''
主类
    开始游戏
    结束游戏
坦克类（我方，敌方）
    移动
    发射
    显示
墙壁类
    阻挡属性
    显示
子弹类
    移动
    显示
爆炸效果
    显示
音乐类
    播放音乐
'''

# 窗口大小
Mainwidth=1000
Mainhight=520
# 背景色
bgcolor=pygame.color.Color(144,250,183)
# 敌方坦克数目dddddddddddddd
ENEMY_number=30
# 敌方坦克速度
ENEMY_tank_speed=2
# 敌方子弹速度
ENEMY_bullet_speed=7
# 我方坦克速度
MY_tank_speed=3
# 我方子弹速度
MY_bullet_speed=3
# 我方坦克最大发射子弹数量
Alivebullet=3
# 爆炸效果时间控制
Bloom_time=2
# 敌方子弹间隔时间
ENEMY_bullettime=50
# 主类
class Maintank():
    window=None
    My_tank=None
    lock=None
    box=None
    exit=False
    enemytank=[]
    enemy_bullets=[]
    all_bullets=[]
    my_bullets=[]
    blooms=[]
    walls=[]
    def __init__(self):
        pass
    # 开始游戏（主页面运行）
    def startgame(self):
        # 初始化窗口
        pygame.display.init()
        Maintank.window=pygame.display.set_mode(size=(Mainwidth,Mainhight))
        pygame.display.set_caption('无郁坦克大战！')
        # 初始化背景图片
        self.bgpic=pygame.image.load('./img/bg.gif')
        # 初始化背景音乐
        self.bgmusic=sound('music/bm.wav')
        self.bgmusic.playsound(0.1,-1)
        # 初始化我的坦克
        self.My_tank=tanks(0,480)
        # 初始化敌方坦克
        self.init_enemy()
        # 初始化墙壁
        self.init_walls()
        # 初始化钥匙和箱子
        self.lock=key(self.My_tank)
        self.box=box(self.My_tank)
        while True:
            print(len(self.all_bullets))
            # 设置背景色（消除每次残迹）
            self.window.blit(self.bgpic,(0,0))
            # 对窗口操作监控
            self.getEvent()
            # 显示坦克（移动）
            self.tankdisplay()
            # 显示我方子弹（移动）
            self.My_tank.tankshoot(self.My_tank.bullets)
            # 显示敌方坦克（移动）
            self.Etankdisplay()
            # 显示敌方爆炸
            self.bloomdisplay()
            # 子弹管理
            self.bulletdisplay()
            self.addbullets()
            # 显示墙壁
            self.walldisplay()
            # 显示文本
            self.textdisplay()
            # 显示钥匙
            self.lock.keydisplay()
            self.box.boxdisplay()
            # 页面刷新
            if self.exit:
                self.endgame()
            pygame.display.update()
            time.sleep(0.02)
    def tankdisplay(self):
        if self.My_tank.alive:
            self.My_tank.tankdisplay()
            self.My_tank.tankmove()
            self.My_tank.hitwall()
            self.My_tank.MYtank_ENEMYbullet_body()
    def Etankdisplay(self):
        for et in self.enemytank:
            if et.alive:
                et.hitwall()
                et.tankdisplay()
                et.etankmove()
                et.ENEMYtank_MYbullet()
                et.etankshoot()
            else:
                self.blooms.append(explore(et))
                self.enemytank.remove(et)
    def bulletdisplay(self):
        for bullet in self.all_bullets:
            if bullet.alive:
                bullet.bulletmove()
                bullet.bulletdisplay()
    def bloomdisplay(self):
        for bloom in self.blooms:
                if  bloom.alive:
                    bloom.exploredisplay()
                else:
                    self.blooms.remove(bloom)
    def walldisplay(self):
        for wall in self.walls:
            wall.walldestroy()
            if wall.alive:
                wall.walldisplay()
            else:
                self.walls.remove(wall)
    def addbullets(self):
        for i in self.all_bullets:
            if i.alive==False:
                self.all_bullets.remove(i)
        for i in self.my_bullets:
            if i.alive==False:
                self.my_bullets.remove(i)
        for i in self.enemy_bullets:
            if i.alive==False:
                self.enemy_bullets.remove(i)
    def textdisplay(self):
        self.text=['敌方坦克还剩：'+str(len(self.enemytank)),'你已经复活{0}次了！'.format(str(self.My_tank.live))]
        pygame.font.init()
        font=pygame.font.SysFont('kaiti',24)
        self.textsurfuce1=font.render(self.text[0],True,(255,0,0))
        self.window.blit(self.textsurfuce1,(0,0))
        self.textsurfuce1=font.render(self.text[1],True,(255,0,0))
        self.window.blit(self.textsurfuce1,(700,0))


    # 初始化敌方坦克函数
    def init_enemy(self):
        for i in range(ENEMY_number):
            e1=Enemytank()
            self.enemytank.append(e1)
    def init_walls(self):
        wall=[[2,8],[5,11],[1,11],[3,9],[5,7],(680,160),(680,320),(880,240),(640,80),(640,400),(120,360)]
        for i in wall[0]:
            for j in range(13):
                left=i*40
                top= 520-j*40
                Maintank.walls.append(ironwall(left=left,top=top))
        for i in wall[1]:
            for j in range(12):
                left=i*40
                top= j*40
                Maintank.walls.append(ironwall(left=left,top=top))
        for i in range(13):
            left=13*40
            top=i*40
            Maintank.walls.append(forrestwall(left=left,top=top))
        for i in range(9):
            left=15*40
            top=i*40+80
            if not (top==wall[10][0] or top==wall[10][1]):
                Maintank.walls.append(icewall(left=left,top=top))
        for i in wall[2]:
            for j in range(9):
                left=j*40+15*40
                top=i*40
                Maintank.walls.append(icewall(left=left,top=top))
        for i in range(7):
            left=18*40
            top=(i+3)*40
            if not (top==wall[5][1] or top==wall[6][1]):
                Maintank.walls.append(glodwall(left=left,top=top))
        for i in wall[3]:
            for j in range(6):
                left=j*40+19*40
                top=i*40
                Maintank.walls.append(glodwall(left=left,top=top))
        for i in range(3):
            left=20*40
            top=(i+5)*40
            Maintank.walls.append(copperwall(left=left,top=top))
        for i in wall[4]:
            for j in range(4):
                left=j*40+20*40
                top=i*40
                Maintank.walls.append(copperwall(left=left,top=top))
        for i in range(3):
            left=17*40
            top=(i+5)*40
            Maintank.walls.append(glodwall(left=left,top=top))
        for i in wall[7:10]:
            Maintank.walls.append(copperwall(left=i[0],top=i[1]))
        for i in range(2):
            Maintank.walls.append(icewall(left=i*40,top=400))



    # 操作设置函数
    def getEvent(self):
        events=pygame.event.get()
        for event in events:
            if event.type==pygame.QUIT:
                self.endgame()
            else:
                self.My_tank.tankevent(event,self.My_tank)

    # 结束游戏函数
    def endgame(self):
        print('exit')
        exit()

# 坦克类
class tanks():
    bullets=[]
    def __init__(self,left,top):
        self.live=0
        self.keyTAG=False
        self.alive=True
        self.uTAG=False
        self.dTAG=False
        self.rTAG=False
        self.lTAG=False
        self.oldleft=left
        self.oldtop=top
        self.i=0
        # 加载图片
        self.tankimgs={
            'u':pygame.image.load('./img/u.png'),
            'l':pygame.image.load('./img/l.png'),
            'r':pygame.image.load('./img/r.png'),
            'd':pygame.image.load('./img/d.png')
                      }
        # 初始化坦克方向
        self.direction='u'
        self.tankimg=self.tankimgs[self.direction]
        # 获取坦克所在矩形块
        self.rect=self.tankimg.get_rect()
        # 调整坦克位置
        self.rect.left=left
        self.rect.top=top
        # 调整坦克速度
        self.speed=MY_tank_speed
        self.shoot=None

    # 坦克移动函数
    def tankmove(self):
        self.oldtop=self.rect.top
        self.oldleft=self.rect.left
        if self.direction=='u':
            if self.rect.top>0:
                if self.uTAG:
                    self.rect.top-=self.speed
        elif self.direction=='d':
            if self.rect.top<Mainhight-self.rect.height:
                if self.dTAG:
                    self.rect.top+=self.speed
        elif self.direction=='r':
            if self.rect.left<Mainwidth-self.rect.width:
                if self.rTAG:
                    self.rect.left+=self.speed
        elif self.direction=='l':
            if self.rect.left>0:
                if self.lTAG:
                    self.rect.left-=self.speed

    # 坦克射击函数
    def tankshoot(self,bullets):
            for bullet in bullets:
                if bullet.alive:
                    bullet.bulletmove()
                    bullet.bulletdisplay()
                else:
                    self.bullets.remove(bullet)

    # 坦克变身函数
    def change(self):
        self.tankimgslist=[{
            'u':pygame.image.load('./img/7.gif'),
            'l':pygame.image.load('./img/e2l.png'),
            'r':pygame.image.load('./img/e2r.png'),
            'd':pygame.image.load('./img/e2d.png')
                      },
                            {
            'u':pygame.image.load('./img/u.png'),
            'd':pygame.image.load('./img/d.png'),
            'r':pygame.image.load('./img/r.png'),
            'l':pygame.image.load('./img/l.png')
                    },
                            {
            'u':pygame.image.load('./img/e3u.png'),
            'd':pygame.image.load('./img/e3d.png'),
            'r':pygame.image.load('./img/e3r.png'),
            'l':pygame.image.load('./img/e3l.png')
                    }]
        self.tankimgs=self.tankimgslist[self.i%len(self.tankimgslist)]
        self.i+=1

    # 坦克显示函数
    def tankdisplay(self):
        self.tankimg=self.tankimgs[self.direction]
        Maintank.window.blit(self.tankimg,self.rect)

    # 坦克操作函数
    def tankevent(self,event,tank):
            if event.type==pygame.KEYDOWN :
                if event.key==pygame.K_d:
                    self.direction='r'
                    self.rTAG=True
                elif event.key==pygame.K_a:
                    self.direction='l'
                    self.lTAG=True
                elif event.key==pygame.K_w:
                    self.direction='u'
                    self.uTAG=True
                elif event.key==pygame.K_s:
                    self.direction='d'
                    self.dTAG=True
                elif event.key==pygame.K_j:
                    if self.alive:
                        if len(self.bullets)<Alivebullet:
                            shoot=bullet(tank)
                            self.bullets.append(shoot)
                            m=music('music/biu.mp3')
                            m.playmusic(1,0.1)
                            Maintank.all_bullets.append(shoot)
                            Maintank.my_bullets.append(shoot)
                elif event.key==pygame.K_SPACE:
                    self.change()
                elif event.key==pygame.K_q:
                    self.alive=True
                    self.live+=1
            elif event.type==pygame.KEYUP :
                if event.key==pygame.K_d:
                    self.rTAG=False
                elif event.key==pygame.K_a:
                    self.lTAG=False
                elif event.key==pygame.K_w:
                    self.uTAG=False
                elif event.key==pygame.K_s:
                    self.dTAG=False
    def MYtank_ENEMYbullet_body(self):
        for eb in Maintank.enemy_bullets:
            if pygame.sprite.collide_rect(eb,self):
                Maintank.blooms.append(explore(self))
                self.rect.top=480
                self.rect.left=0
                eb.alive=False
                self.alive=False
        for etank in Maintank.enemytank:
            if pygame.sprite.collide_rect(etank,self):
                Maintank.blooms.append(explore(self))
                self.rect.top=480
                self.rect.left=0
                self.alive=False
    def hitwall(self):
        for wall in Maintank.walls:
            if pygame.sprite.collide_rect(wall,self):
                self.rect.top=self.oldtop
                self.rect.left=self.oldleft

# 敌方坦克
class Enemytank(tanks,pygame.sprite.Sprite):

    def __init__(self):
        self.delay=ENEMY_bullettime
        self.change=0
        self.alive=True
        self.ad=[(280,240),(400,240),(760,240),(760,240),(920,240)]
        i=random.randint(0,4)
        self.oldleft=self.ad[i][0]
        self.oldtop=self.ad[i][1]
        # 敌方坦克速度
        self.speed=ENEMY_tank_speed
        # 随机敌方坦克转向位置
        self.rowtran=random.randrange(10,650,self.speed)
        self.columntran=random.randrange(10,450,self.speed)
        # 导入图片
        self.tankimgs={
            'u':pygame.image.load('./img/e1u.png'),
            'd':pygame.image.load('./img/e1d.png'),
            'r':pygame.image.load('./img/e1r.png'),
            'l':pygame.image.load('./img/e1l.png')
                    }

        self.directions={1:'u',2:'d',3:'r',4:'l'}
        # 随机朝向及图片对应
        self.direction=self.directions[random.randint(1,4)]
        self.tankimg=self.tankimgs[self.direction]
        # 随机敌方坦克位置
        self.rect=self.tankimg.get_rect()
        self.left=random.randrange(10,650,self.speed)
        self.top=random.randrange(10,450,self.speed)
        self.rect.left=self.left
        self.rect.top=self.top

    # 敌方坦克移动函数
    def etankmove(self):
        self.oldtop=self.rect.top
        self.oldleft=self.rect.left
        if self.alive:
            if self.direction=='u':
                # 防止出边
                if self.rect.top>0:
                    self.rect.top-=self.speed
                    # 随机转向
                    if self.rect.top==self.columntran:
                        self.direction=self.directions[random.randint(1,4)]
                        self.columntran=random.randrange(10,450,self.speed)
                # 到达边界转向
                elif self.rect.top<=0:
                    self.direction=self.directions[random.randint(2,4)]

            elif self.direction=='d':
                if self.rect.top<Mainhight-self.rect.height:
                    self.rect.top+=self.speed
                    if self.rect.top==self.columntran:
                        self.direction=self.directions[random.randint(1,4)]
                        self.columntran=random.randrange(10,450,self.speed)
                elif self.rect.top>=Mainhight-self.rect.height:
                    self.direction=self.directions[random.randint(1,4)]

            elif self.direction=='r':
                if self.rect.left<Mainwidth-self.rect.width:
                        self.rect.left+=self.speed
                        if self.rect.left==self.rowtran:
                            self.direction=self.directions[random.randint(1,4)]
                            self.rowtran=random.randrange(10,650,self.speed)
                elif self.rect.left>=Mainwidth-self.rect.width:
                    self.direction=self.directions[random.randint(1,4)]
                    self.rowtran=random.randrange(10,650,self.speed)

            elif self.direction=='l':
                if self.rect.left>0:
                        self.rect.left-=self.speed
                        if self.rect.left==self.rowtran:
                            self.direction=self.directions[random.randint(1,4)]
                            self.rowtran=random.randrange(10,650,self.speed)
                elif self.rect.left<=0:
                    self.direction=self.directions[random.randint(1,4)]
                    self.rowtran=random.randrange(10,650,self.speed)

    def etankshoot(self):
        if self.alive:
            self.delay-=1
            if self.delay==0:
                b1=bullet(self)
                b1.bullet_speed=ENEMY_bullet_speed
                Maintank.all_bullets.append(b1)
                Maintank.enemy_bullets.append(b1)
                self.delay=ENEMY_bullettime

    def ENEMYtank_MYbullet(self):
        for bullet in tanks.bullets:
            if pygame.sprite.collide_rect(self,bullet):
                bullet.alive=False
                self.alive=False
    def hitwall(self):
        for wall in Maintank.walls:
            if pygame.sprite.collide_rect(self,wall):
                self.rect.top=self.oldtop
                self.rect.left=self.oldleft
                self.direction=self.directions[random.randint(1,4)]

# 子弹类
class bullet():

    def __init__(self,tank):
        self.tank=tank
        self.alive=True
        # 我方子弹速度
        self.bullet_speed=MY_bullet_speed
        # 方向调整
        self.direction=tank.direction
        self.bulletimgs={
            'u':pygame.image.load('./img/bullet_u.png'),
            'l':pygame.image.load('./img/bullet_l.png'),
            'r':pygame.image.load('./img/bullet_r.png'),
            'd':pygame.image.load('./img/bullet_d.png')
                        }
        self.rect=self.bulletimgs[tank.direction].get_rect()
        # 子弹初始发射位置调整
        if tank.direction == 'u':
            self.rect.top=tank.rect.top-self.rect.height
            self.rect.left=tank.rect.left+tank.rect.width//3
        elif tank.direction == 'd':
            self.rect.top=tank.rect.top+self.rect.height
            self.rect.left=tank.rect.left+tank.rect.width//3
        elif tank.direction == 'r':
            self.rect.top=tank.rect.top+tank.rect.height//3
            self.rect.left=tank.rect.left+tank.rect.width
        elif tank.direction == 'l':
            self.rect.top=tank.rect.top+self.rect.height//3
            self.rect.left=tank.rect.left-self.rect.width

    # 子弹移动函数
    def bulletmove(self):
        if self.direction == 'u':
            self.rect.top-=self.bullet_speed
        elif self.direction == 'd':
            self.rect.top+=self.bullet_speed
        elif self.direction == 'r':
            self.rect.left+=self.bullet_speed
        elif self.direction == 'l':
            self.rect.left-=self.bullet_speed

    # 子弹展示函数
    def bulletdisplay(self):
        # 消除出界子弹
        if self.rect.top>0 and self.rect.left>0 and self.rect.top<Mainhight-self.rect.height and self.rect.left<Mainwidth-self.rect.width:
            self.bulletimg=self.bulletimgs[self.direction]
            Maintank.window.blit(self.bulletimg,self.rect)
        else:
            self.alive=False

# 墙壁类
class wall(pygame.sprite.Sprite):
    def __init__(self,top,left):
        self.delay=None
        self.alive=True
        self.top=top
        self.left=left
        self.imag=pygame.image.load('./img/wall/ice.gif')
        self.hit=None
        self.rect=self.imag.get_rect()
        self.rect.top=self.top
        self.rect.left=self.left

    def walldisplay(self):
        Maintank.window.blit(self.imag,self.rect)
    def walldestroy(self):
        for bullet in Maintank.all_bullets:
            if pygame.sprite.collide_rect(bullet,self):
                bullet.alive=False
                if Maintank.my_bullets.count(bullet)!=0:
                    self.hit-=1
                    if self.hit==0:
                        self.alive=False
class icewall(wall):
    def __init__(self,top,left):
        super().__init__(top=top,left=left)
        self.imag=pygame.image.load('./img/wall/ice.gif')
        self.hit=2
class forrestwall(wall):
    def __init__(self,top,left):
        super().__init__(top=top,left=left)
        self.imag=pygame.image.load('./img/wall/forrest.gif')
        self.hit=3
class copperwall(wall):
    def __init__(self,top,left):
        super().__init__(top=top,left=left)
        self.imag=pygame.image.load('./img/wall/copper.gif')
        self.hit=6
class ironwall(wall):
    def __init__(self,top,left):
        super().__init__(top=top,left=left)
        self.imag=pygame.image.load('./img/wall/iron.gif')
        self.hit=1000
class glodwall(wall):
    def __init__(self,top,left):
        super().__init__(top=top,left=left)
        self.imag=pygame.image.load('./img/wall/glod.gif')
        self.hit=10
# 爆炸类
class explore():
    def __init__(self,tank):
        self.top=tank.rect.top
        self.left=tank.rect.left
        self.FPS=Bloom_time
        self.bloomlist=[pygame.image.load('./img/bloom/'+str(i)+'.png') for i in range(1,17)]
        self.bloom=None
        self.pic=0
        self.alive=True
        self.delay=0
    def exploredisplay(self):
        self.bloom=self.bloomlist[self.pic]
        self.rect=self.bloom.get_rect()
        self.rect.top=self.top
        self.rect.left=self.left
        Maintank.window.blit(self.bloom,self.rect)
        if self.delay>=self.FPS:
            self.delay=0
            self.pic+=1
            if self.pic<len(self.bloomlist):
                self.bloom=self.bloomlist[self.pic]
            else:
                self.alive=False
        else:
            self.delay+=1
# 钥匙
class key(pygame.sprite.Sprite,):
    def __init__(self,tank):
        self.tank=tank
        self.alive=True
        self.wall=Maintank.walls[random.randint(48,len(Maintank.walls))]
        self.top=self.wall.top
        self.left=self.wall.left
        self.img=pygame.image.load('./img/wall/key.gif')
        self.rect=self.img.get_rect()
        self.rect.left=self.left
        self.rect.top=self.top
    def keydisplay(self):
        if  not self.wall.alive:
            if self.alive:
                Maintank.window.blit(self.img,self.rect)
                if pygame.sprite.collide_rect(self.tank,self) :
                    self.alive=False
                    bullet.alive=False
                    self.tank.keyTAG=True

class box(pygame.sprite.Sprite):
    def __init__(self,tank):
        self.tank=tank
        self.img=pygame.image.load('./img/wall/box.gif')
        self.rect=self.img.get_rect()
        self.rect.top=245
        self.rect.left=845
    def boxdisplay(self):
        Maintank.window.blit(self.img,self.rect)
        if pygame.sprite.collide_rect(self,self.tank):
            if self.tank.keyTAG:
                Maintank.exit=True

# 音乐类
class music():
    def __init__(self,filename):
        pygame.mixer.init()
        pygame.mixer.music.load(filename)
    def playmusic(self,time,volum):
        pygame.mixer.music.set_volume(volum)
        pygame.mixer.music.play(time)
class sound():
    def __init__(self,filename):
        pygame.mixer.init()
        self.sound=pygame.mixer.Sound(filename)
    def playsound(self,volume,time):
        self.sound.set_volume(volume)
        self.sound.play(time)

if __name__=='__main__':
    Maintank().startgame()
